package com.beyondsoft.mcms.web;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.roo.addon.web.mvc.controller.finder.RooWebFinder;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.beyondsoft.mcms.common.CommonUtils;
import com.beyondsoft.mcms.common.Constants;
import com.beyondsoft.mcms.common.ExcelDataElement;
import com.beyondsoft.mcms.common.ExcelExportUtils;
import com.beyondsoft.mcms.common.I18NUtils;
import com.beyondsoft.mcms.domain.Advice;
import com.beyondsoft.mcms.domain.Attendee;
import com.beyondsoft.mcms.domain.Conference;
import com.beyondsoft.mcms.domain.Item;
import com.beyondsoft.mcms.domain.MemberInfo;

@RequestMapping("/advices")
@Controller
@RooWebScaffold(path = "advices", formBackingObject = Advice.class, update = false, delete = false)
@RooWebFinder
public class AdviceController {

    @RequestMapping(method = RequestMethod.POST, produces = "text/html")
    public String create(@Valid Advice advice, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors()) {
            populateEditForm(uiModel, advice);
            return "advices/create";
        }
        uiModel.asMap().clear();
        advice.persist();
        return "redirect:/advices/" + encodeUrlPathSegment(advice.getId().toString(), httpServletRequest);
    }

    @RequestMapping(params = "form", produces = "text/html")
    public String createForm(Model uiModel) {
        Advice advice = new Advice();
        advice.setCreateDate(new Date());
        advice.setCreatedBy(CommonUtils.getCurrentUsername());
        populateEditForm(uiModel, advice);
        return "advices/create";
    }

    void populateEditForm(Model uiModel, Advice advice) {
        uiModel.addAttribute("advice", advice);
        addDateTimeFormatPatterns(uiModel);
        List<Conference> conferences = Conference.findConferencesByNameLikeAndConferenceTypeAndConferenceStatus(null, null, Item.findItem(new Long(Constants.CONFERENCE_STATUS_REGISTERING))).getResultList();
        List<MemberInfo> memberinfoes = MemberInfo.findAllMemberInfoes();
        uiModel.addAttribute("conferences", conferences);
        uiModel.addAttribute("memberinfoes", memberinfoes);
        List<String[]> dependencies = new ArrayList<String[]>();
        if (conferences.size() == 0) {
            dependencies.add(new String[] { "conference", "conferences" });
        }
        if (memberinfoes.size() == 0) {
            dependencies.add(new String[] { "memberinfo", "memberinfoes" });
        }
        uiModel.addAttribute("dependencies", dependencies);
    }

    @RequestMapping(params = { "find=ByConferenceAndMemberInfo", "form" }, method = RequestMethod.GET)
    public String findAdvicesByConferenceAndMemberInfoForm(Model uiModel) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        request.getSession().setAttribute("memberInfo", null);
        request.getSession().setAttribute("conference", null);
        return findAdvicesByConferenceAndMemberInfo(null, null, uiModel);
    }

    @RequestMapping(params = "find=ByConferenceAndMemberInfo", method = RequestMethod.GET)
    public String findAdvicesByConferenceAndMemberInfo(@RequestParam(value = "conference", required = false) Conference conference, @RequestParam(value = "memberInfo", required = false) MemberInfo memberInfo, Model uiModel) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String page = request.getParameter("page");
        String size = request.getParameter("size");
        int sizeNo = size == null ? 10 : Integer.valueOf(size);
        int pageNo = page == null ? 1 : Integer.valueOf(page);
        if (page != null && size != null) {
            conference = (Conference) request.getSession().getAttribute("conference");
            memberInfo = (MemberInfo) request.getSession().getAttribute("memberInfo");
        } else {
            request.getSession().setAttribute("conference", conference);
            request.getSession().setAttribute("memberInfo", memberInfo);
        }
        uiModel.addAttribute("conference", conference);
        uiModel.addAttribute("memberInfo", memberInfo);
        return list(pageNo, sizeNo, uiModel);
    }

    @RequestMapping(produces = "text/html")
    public String list(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
        uiModel.addAttribute("conferences", Conference.findAllConferences());
        uiModel.addAttribute("memberinfoes", MemberInfo.findAllMemberInfoes());
        Conference conference = (Conference) uiModel.asMap().get("conference");
        MemberInfo memberInfo = (MemberInfo) uiModel.asMap().get("memberInfo");
        int sizeNo = size == null ? 10 : size.intValue();
        final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
        float nrOfPages = 0.0f;
        List<Advice> advices = Advice.findAdvicesByConferenceAndMemberInfo(conference, memberInfo).getResultList();
        int lastResult = (advices.size() > (sizeNo + firstResult)) ? (sizeNo + firstResult) : advices.size();
        nrOfPages = (float) advices.size() / sizeNo;
        uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
        uiModel.addAttribute("advices", advices.subList(firstResult, lastResult));
        uiModel.addAttribute("find", "ByConferenceAndMemberInfo"); // differ
        // non-query
        // request
        uiModel.addAttribute("selectQueryIds", (conference == null ? "-1" : conference.getId()) + "," + (memberInfo == null ? "-1" : memberInfo.getId()));
        addDateTimeFormatPatterns(uiModel);
        return "advices/list";
    }

    @RequestMapping(value = "/{id}", params = "childs", method = RequestMethod.GET)
    public String listAttendees(@PathVariable("id") Long id, Model uiModel, HttpServletRequest httpServletRequest) {
        return "redirect:/attendees/list/" + encodeUrlPathSegment(id.toString(), httpServletRequest);
    }

    @RequestMapping(params = { "find=ByConference", "form" }, method = RequestMethod.GET)
    public String findAdvicesByConferenceForm(Model uiModel) {
        uiModel.addAttribute("conferences", Conference.findAllConferences());
        return "advices/findAdvicesByConference";
    }

    @RequestMapping(params = "find=ByConference", method = RequestMethod.GET)
    public String findAdvicesByConference(@RequestParam("conference") Conference conference, Model uiModel) {
        uiModel.addAttribute("advices", Advice.findAdvicesByConference(conference).getResultList());
        return "advices/list";
    }

    @RequestMapping(value = "reportByConference", method = RequestMethod.GET)
    public String reportByConference(@RequestParam("conference") Conference conference, Model uiModel) {
        List<Advice> advices = Advice.findAdvicesByConference(conference).getResultList();
        uiModel.addAttribute("conferenceName", conference.getName());
        uiModel.addAttribute("shouldAttendMenberCount", advices.size());
        uiModel.addAttribute("signUpAttendMenberCount", Attendee.countAttendMemberInfo(conference, Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED));
        uiModel.addAttribute("attendedMenberCount", Attendee.countAttendMemberInfo(conference, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED));
        uiModel.addAttribute("signUpAttendPeopleCount", Attendee.countAttendes(conference, null, Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED));
        uiModel.addAttribute("attendedPeopleCount", Attendee.countAttendes(conference, null, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED));
        List<Map<String, Object>> memberAttends = new ArrayList<Map<String, Object>>();
        uiModel.addAttribute("memberAttends", memberAttends);
        uiModel.addAttribute("conference", conference);
        for (Advice advice : advices) {
            Map<String, Object> memberAttendMap = new HashMap<String, Object>();
            memberAttendMap.put("memberName", advice.getMemberInfo().getMemberName());
            memberAttendMap.put("signUpAttendPeopleCount", Attendee.countAttendes(conference, advice.getMemberInfo(), Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED));
            memberAttendMap.put("attendedPeopleCount", Attendee.countAttendes(conference, advice.getMemberInfo(), Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED));
            memberAttends.add(memberAttendMap);
        }
        return "advices/reportByConference";
    }

    @RequestMapping(value = "/reportByConference/{conference}", params = "exportExcel", method = RequestMethod.GET)
    public String reportByConference(@PathVariable("conference") Conference conference, HttpServletRequest httpServletRequest, HttpServletResponse response) {
        String title = I18NUtils.getMessage("label_report_by_conference_title", conference.getName());
        List<Advice> advices = Advice.findAdvicesByConference(conference).getResultList();
        List<ExcelDataElement<?>> exportDatas = new ArrayList<ExcelDataElement<?>>();
        exportDatas.add(new ExcelDataElement<String>(title, 4, ExcelDataElement.FONT_SIZE_16, true));
        exportDatas.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_subtitle1"), 4, ExcelDataElement.FONT_SIZE_14, true));
        List<ExcelDataElement<?>> exportDataTitle = new ArrayList<ExcelDataElement<?>>();
        exportDatas.add(new ExcelDataElement<List<ExcelDataElement<?>>>(exportDataTitle));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_should_attend_member"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_singup_attend_member"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_attended_member"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_singup_attend_people"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_attended_people"), 0, ExcelDataElement.FONT_SIZE_11, true));
        List<ExcelDataElement<?>> exportData = new ArrayList<ExcelDataElement<?>>();
        exportDatas.add(new ExcelDataElement<List<ExcelDataElement<?>>>(exportData));
        exportData.add(new ExcelDataElement<Integer>(advices.size()));
        exportData.add(new ExcelDataElement<Long>(Attendee.countAttendMemberInfo(conference, Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED)));
        exportData.add(new ExcelDataElement<Long>(Attendee.countAttendMemberInfo(conference, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED)));
        exportData.add(new ExcelDataElement<Long>(Attendee.countAttendes(conference, null, Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED)));
        exportData.add(new ExcelDataElement<Long>(Attendee.countAttendes(conference, null, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED)));
        exportDatas.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_subtitle2"), 4, ExcelDataElement.FONT_SIZE_14, true));
        exportDataTitle = new ArrayList<ExcelDataElement<?>>();
        exportDatas.add(new ExcelDataElement<List<ExcelDataElement<?>>>(exportDataTitle));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_th_index"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_adviced_member"), 1, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_singup_attend_people"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_attended_people"), 0, ExcelDataElement.FONT_SIZE_11, true));
        int index = 1;
        for (Advice advice : advices) {
            exportData = new ArrayList<ExcelDataElement<?>>();
            exportDatas.add(new ExcelDataElement<List<ExcelDataElement<?>>>(exportData));
            exportData.add(new ExcelDataElement<Integer>(index++));
            exportData.add(new ExcelDataElement<String>(advice.getConference().getName(), 1));
            exportData.add(new ExcelDataElement<Long>(Attendee.countAttendes(conference, advice.getMemberInfo(), Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED)));
            exportData.add(new ExcelDataElement<Long>(Attendee.countAttendes(conference, advice.getMemberInfo(), Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED)));
        }
        Workbook workbook = ExcelExportUtils.createWorkbook(title, exportDatas);
        response.setHeader("Content-Disposition", "inline;filename=\"" + encodeUrlPathSegment(title, httpServletRequest) + ".xls\"");
        OutputStream out;
        try {
            out = response.getOutputStream();
            response.setContentType("application/vnd.ms-excel ");
            workbook.write(out);
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping(value = "reportByMemberInfo", method = RequestMethod.GET)
    public String reportByMemberInfo(@RequestParam("memberInfo") MemberInfo memberInfo, Model uiModel) {
        List<Advice> advices = Advice.findAdvicesByMemberInfo(memberInfo, Constants.CONFERENCE_STATUS_ENDED).getResultList();
        uiModel.addAttribute("memberInfo", memberInfo);
        uiModel.addAttribute("memberName", memberInfo.getMemberName());
        uiModel.addAttribute("shouldAttendConferenceCount", advices.size());
        uiModel.addAttribute("signUpAttendConferenceCount", Attendee.countAttendConference(memberInfo, Constants.CONFERENCE_STATUS_ENDED, Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED));
        uiModel.addAttribute("attendedConferenceCount", Attendee.countAttendConference(memberInfo, Constants.CONFERENCE_STATUS_ENDED, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED));
        List<Map<String, Object>> conferenceAttends = new ArrayList<Map<String, Object>>();
        uiModel.addAttribute("conferenceAttends", conferenceAttends);
        for (Advice advice : advices) {
            Map<String, Object> attendMap = new HashMap<String, Object>();
            attendMap.put("conferenceName", advice.getConference().getName());
            attendMap.put("conferenceDate", advice.getConference().getHoldDate());
            attendMap.put("conferenceTime", advice.getConference().getHoldTime());
            attendMap.put("signUpAttendPeopleCount", Attendee.countAttendes(advice.getConference(), advice.getMemberInfo(), Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED));
            attendMap.put("attendedPeopleCount", Attendee.countAttendes(advice.getConference(), advice.getMemberInfo(), Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED));
            conferenceAttends.add(attendMap);
        }
        return "advices/reportByMemberInfo";
    }

    @RequestMapping(value = "/reportByMemberInfo/{memberInfo}", params = "exportExcel", method = RequestMethod.GET)
    public String reportByMemberInfo(@PathVariable("memberInfo") MemberInfo memberInfo, HttpServletRequest httpServletRequest, HttpServletResponse response) {
        String title = I18NUtils.getMessage("label_report_by_member_title", memberInfo.getMemberName());
        List<Advice> advices = Advice.findAdvicesByMemberInfo(memberInfo, Constants.CONFERENCE_STATUS_ENDED).getResultList();
        List<ExcelDataElement<?>> exportDatas = new ArrayList<ExcelDataElement<?>>();
        exportDatas.add(new ExcelDataElement<String>(title, 4, ExcelDataElement.FONT_SIZE_16, true));
        exportDatas.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_member_subtitle1"), 4, ExcelDataElement.FONT_SIZE_14, true));
        List<ExcelDataElement<?>> exportDataTitle = new ArrayList<ExcelDataElement<?>>();
        exportDatas.add(new ExcelDataElement<List<ExcelDataElement<?>>>(exportDataTitle));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_member_th_should_attend_conference"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_member_th_singup_attend_conference"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_member_th_nosingup_attend_conference"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_member_th_singup_noattend_conference"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_member_th_attended_conference"), 0, ExcelDataElement.FONT_SIZE_11, true));
        List<ExcelDataElement<?>> exportData = new ArrayList<ExcelDataElement<?>>();
        exportDatas.add(new ExcelDataElement<List<ExcelDataElement<?>>>(exportData));
        exportData.add(new ExcelDataElement<Integer>(advices.size()));
        long signUpAttendCount = Attendee.countAttendConference(memberInfo, Constants.CONFERENCE_STATUS_ENDED, Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED);
        long AttendedCount = Attendee.countAttendConference(memberInfo, Constants.CONFERENCE_STATUS_ENDED, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED);
        exportData.add(new ExcelDataElement<Long>(signUpAttendCount));
        exportData.add(new ExcelDataElement<Long>(advices.size() - signUpAttendCount));
        exportData.add(new ExcelDataElement<Long>(signUpAttendCount - AttendedCount));
        exportData.add(new ExcelDataElement<Long>(AttendedCount));
        exportDatas.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_member_subtitle1"), 4, ExcelDataElement.FONT_SIZE_14, true));
        exportDataTitle = new ArrayList<ExcelDataElement<?>>();
        exportDatas.add(new ExcelDataElement<List<ExcelDataElement<?>>>(exportDataTitle));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_th_index"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_com_beyondsoft_mcms_domain_conference_name"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_com_beyondsoft_mcms_domain_conference_holdtime"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_singup_attend_people"), 0, ExcelDataElement.FONT_SIZE_11, true));
        exportDataTitle.add(new ExcelDataElement<String>(I18NUtils.getMessage("label_report_by_conference_th_attended_people"), 0, ExcelDataElement.FONT_SIZE_11, true));
        int index = 1;
        for (Advice advice : advices) {
            exportData = new ArrayList<ExcelDataElement<?>>();
            exportDatas.add(new ExcelDataElement<List<ExcelDataElement<?>>>(exportData));
            exportData.add(new ExcelDataElement<Integer>(index++));
            exportData.add(new ExcelDataElement<String>(advice.getMemberInfo().getMemberName()));
            exportData.add(new ExcelDataElement<Date>(advice.getConference().getHoldDate(), "yyyy-MM-dd"));
            exportData.add(new ExcelDataElement<Long>(Attendee.countAttendes(advice.getConference(), memberInfo, Constants.ATTENDEE_STATUS_REGISTERED, Constants.ATTENDEE_STATUS_SIGNED)));
            exportData.add(new ExcelDataElement<Long>(Attendee.countAttendes(advice.getConference(), memberInfo, Constants.ATTENDEE_STATUS_SIGNED, Constants.ATTENDEE_STATUS_SIGNED_NOT_REGISTERED)));
        }
        Workbook workbook = ExcelExportUtils.createWorkbook(title, exportDatas);
        response.setHeader("Content-Disposition", "inline;filename=\"" + encodeUrlPathSegment(title, httpServletRequest) + ".xls\"");
        OutputStream out;
        try {
            out = response.getOutputStream();
            response.setContentType("application/vnd.ms-excel ");
            workbook.write(out);
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
